package com.afd.ozblip.net;

import java.io.IOException;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;

import com.afd.ozblip.util.StreamUtil;
import com.alibaba.fastjson.JSON;

/**
 * HTTP传输类
 * 
 * @author 徐鹏
 * 
 */
public class HttpTransport {

	private final HttpClient _client;
	public static HttpTransport httpTransport;

	public HttpTransport() {
		// HttpClient client = new HttpClient(new HttpClientParams(),new
		// SimpleHttpConnectionManager(true) );
		HttpClient client = HttpClientFactory.newInstance(10000);
		this._client = client;
	}

	/**
	 * GET提交方式
	 * 
	 * @param isCMWAP
	 *            是否是CMWAP网络连接
	 * @param getUrl
	 *            提交URL
	 * @param paramMap
	 *            参数Map集合
	 * @throws Exception
	 */
	public byte[] get(boolean isCMWAP, String getUrl,
			Map<String, Object> paramMap) throws Exception {
		// 判断是否是CMWAP网络连接
		if (isCMWAP) {
			return getByCMCCProxy(getUrl, paramMap);
		} else {
			return get(URI.create(getUrl), paramMap);
		}
	}
	/**
	 * GET提交方式
	 * 
	 * @param isCMWAP
	 *            是否是CMWAP网络连接
	 * @param getUrl
	 *            提交URL
	 * @param paramMap
	 *            参数Map集合
	 * @throws Exception
	 */
	public byte[] get(boolean isCMWAP, String getUrl) throws Exception {
		// 判断是否是CMWAP网络连接
		if (isCMWAP) {
			return getByCMCCProxy(getUrl);
		} else {
			return get(URI.create(getUrl));
		}
	}

	/**
	 * POST提交方式
	 * 
	 * @param isCMWAP
	 *            是否是CMWAP网络连接
	 * @param postUrl
	 *            提交URL
	 * @param paramMap
	 *            参数Map集合
	 * @throws Exception
	 */
	public byte[] post(boolean isCMWAP, String postUrl,
			Map<String, Object> paramMap) throws Exception {
		// 判断是否是CMWAP网络连接
		if (isCMWAP) {
			// 通过CMCC(中国移动)协议提交
			return postByCMCCProxy(postUrl, paramMap);
		} else {

			// return post(URI.create(postUrl), paramMap);
			return post(postUrl, paramMap);
		}
	}

	/**
	 * GET方式通过802.11B协议提交
	 * 
	 * @param postUrl
	 *            提交URL
	 * @param paramMap
	 *            参数Map集合
	 * @throws Exception
	 */
	private byte[] get(URI paramURI, Map<String, Object> paramMap)
			throws Exception {
		// 获取httpGet对象
		// 拼接参数
		String parameStr = parametersToString(paramMap);
		// 获取HTTPGet对象
		String getURL = paramURI + "&" + parameStr;
		HttpGet localHttpGet = new HttpGet(getURL);
		// 获取response对象
		HttpResponse localHttpResponse = this._client.execute(localHttpGet);
		// 获取状态行
		StatusLine localStatusLine = localHttpResponse.getStatusLine();
		if (localStatusLine.getStatusCode() != 200)
			throw new IOException("HTTP Response code: "
					+ localStatusLine.getStatusCode() + " - "
					+ localStatusLine.getReasonPhrase());
		// 获取返回数据字节数组
		byte[] arrayOfByte = StreamUtil.receiveData(localHttpResponse
				.getEntity().getContent());
		localHttpGet.abort();
		return arrayOfByte;
	}

	/**
	 * GET方式通过802.11B协议提交
	 * 
	 * @param postUrl
	 *            提交URL
	 * @param paramMap
	 *            参数Map集合
	 * @throws Exception
	 */
	private byte[] get(URI paramURI) throws Exception {
		// 获取httpGet对象
		// 获取HTTPGet对象
		HttpGet localHttpGet = new HttpGet(paramURI);
		// 获取response对象
		HttpResponse localHttpResponse = this._client.execute(localHttpGet);
		// 获取状态行
		StatusLine localStatusLine = localHttpResponse.getStatusLine();
		if (localStatusLine.getStatusCode() != 200)
			throw new IOException("HTTP Response code: "
					+ localStatusLine.getStatusCode() + " - "
					+ localStatusLine.getReasonPhrase());
		// 获取返回数据字节数组
		byte[] arrayOfByte = StreamUtil.receiveData(localHttpResponse
				.getEntity().getContent());
		localHttpGet.abort();
		return arrayOfByte;
	}

	/**
	 * GET方式通过CMCC协议提交
	 * 
	 * @param postUrl
	 *            提交URL
	 * @param paramMap
	 *            参数Map集合
	 * @throws Exception
	 */
	private byte[] getByCMCCProxy(String getURL, Map<String, Object> paramMap)
			throws Exception {
		// 获取Host
		String hostName = getHostByUrl(getURL);
		// 获取端口
		String port = getPortByUrl(getURL);
		HttpHost localHttpHost1 = new HttpHost("10.0.0.172", 80, "http");
		HttpHost localHttpHost2 = new HttpHost(hostName,
				Integer.parseInt(port), "http");
		this._client.getParams().setParameter("http.route.default-proxy",
				localHttpHost1);
		// 拼接参数
		String parameStr = parametersToString(paramMap);
		// 获取HTTPGet对象
		getURL = getURL + "&" + parameStr;
		HttpGet localHttpGet = new HttpGet(getURL);
		// 获取HttpResponse对象
		HttpResponse localHttpResponse = this._client.execute(localHttpHost2,
				localHttpGet);
		// 获取响应状态
		StatusLine localStatusLine = localHttpResponse.getStatusLine();
		if (localStatusLine.getStatusCode() != 200) {
			throw new IOException("HTTP Response code: "
					+ localStatusLine.getStatusCode() + " - "
					+ localStatusLine.getReasonPhrase());
		}
		// 获取返回数据字节数组
		byte[] arrayOfByte = StreamUtil.receiveData(localHttpResponse
				.getEntity().getContent());
		localHttpGet.abort();
		return arrayOfByte;
	}
	/**
	 * GET方式通过CMCC协议提交
	 * 
	 * @param postUrl
	 *            提交URL
	 * @param paramMap
	 *            参数Map集合
	 * @throws Exception
	 */
	private byte[] getByCMCCProxy(String getURL)
			throws Exception {
		// 获取Host
		String hostName = getHostByUrl(getURL);
		// 获取端口
		String port = getPortByUrl(getURL);
		HttpHost localHttpHost1 = new HttpHost("10.0.0.172", 80, "http");
		HttpHost localHttpHost2 = new HttpHost(hostName,
				Integer.parseInt(port), "http");
		this._client.getParams().setParameter("http.route.default-proxy",
				localHttpHost1);
		// 获取HTTPGet对象
		getURL = getURL + "";
		HttpGet localHttpGet = new HttpGet(getURL);
		// 获取HttpResponse对象
		HttpResponse localHttpResponse = this._client.execute(localHttpHost2,
				localHttpGet);
		// 获取响应状态
		StatusLine localStatusLine = localHttpResponse.getStatusLine();
		if (localStatusLine.getStatusCode() != 200) {
			throw new IOException("HTTP Response code: "
					+ localStatusLine.getStatusCode() + " - "
					+ localStatusLine.getReasonPhrase());
		}
		// 获取返回数据字节数组
		byte[] arrayOfByte = StreamUtil.receiveData(localHttpResponse
				.getEntity().getContent());
		localHttpGet.abort();
		return arrayOfByte;
	}

	/**
	 * POST方式通过CMCC协议提交
	 * 
	 * @param postUrl
	 *            提交URL
	 * @param paramMap
	 *            参数Map集合
	 * @throws Exception
	 */
	private byte[] postByCMCCProxy_old(String postUrl,
			Map<String, Object> paramMap) throws Exception {
		// 获取Host
		String hostName = getHostByUrl(postUrl);
		// 获取端口
		String port = getPortByUrl(postUrl);
		// 获取HttpHost对象
		HttpHost localHttpHost1 = new HttpHost("10.0.0.172", 80, "http");
		// 获取HttpHost对象
		HttpHost localHttpHost2 = new HttpHost(hostName,
				Integer.parseInt(port), "http");
		this._client.getParams().setParameter("http.route.default-proxy",
				localHttpHost1);
		// 根据URL获取主机对象
		HttpPost localHttpPost = new HttpPost(postUrl);
		// 添加参数信息
		// 获取参数信息
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		Set<String> keys = paramMap.keySet();
		String[] keyArray = (String[]) keys.toArray();
		for (int i = 0, len = keyArray.length; i < len; i++) {
			params.add(new BasicNameValuePair(keyArray[i], String
					.valueOf(paramMap.get(keyArray[i]))));
		}
		UrlEncodedFormEntity postParamEntity = new UrlEncodedFormEntity(params,
				HTTP.UTF_8);
		postParamEntity.setContentType("application/x-www-form-urlencoded");
		localHttpPost.setEntity(postParamEntity);
		// 获取HTTPResponse对象
		HttpResponse localHttpResponse = this._client.execute(localHttpHost2,
				localHttpPost);
		// 获取响应状态值
		StatusLine localStatusLine = localHttpResponse.getStatusLine();
		// 判断返回状态是否正常
		if (localStatusLine.getStatusCode() != 200) {
			throw new IOException("HTTP Response code: "
					+ localStatusLine.getStatusCode() + " - "
					+ localStatusLine.getReasonPhrase());
		}
		// 获取返回数据字节数组
		byte[] arrayOfByte = StreamUtil.receiveData(localHttpResponse
				.getEntity().getContent());
		// 终止HTTP请求
		localHttpPost.abort();
		return arrayOfByte;
	}

	/**
	 * POST方式通过CMCC协议提交
	 * 
	 * @param postUrl
	 *            提交URL
	 * @param paramMap
	 *            参数Map集合
	 * @throws Exception
	 */
	private byte[] postByCMCCProxy(String postUrl, Map<String, Object> paramMap)
			throws Exception {
		byte[] arrayOfByte = null;
		try {
			// 建立连接
			URL url = new URL(postUrl);
			HttpURLConnection httpConn = (HttpURLConnection) url
					.openConnection();

			// //设置连接属性
			httpConn.setDoOutput(true);// 使用 URL 连接进行输出
			httpConn.setDoInput(true);// 使用 URL 连接进行输入
			httpConn.setUseCaches(false);// 忽略缓存
			httpConn.setRequestMethod("POST");// 设置URL请求方法
			String requestString = JSON.toJSONString(paramMap);

			// 设置请求属性
			// 获得数据字节数据，请求数据流的编码，必须和下面服务器端处理请求流的编码一致
			byte[] requestStringBytes = requestString.getBytes(HTTP.UTF_8);
			httpConn.setRequestProperty("Content-length", ""
					+ requestStringBytes.length);
			httpConn.setRequestProperty("Content-Type",
					"application/octet-stream");
			httpConn.setRequestProperty("Connection", "Keep-Alive");// 维持长连接
			httpConn.setRequestProperty("Charset", "UTF-8");

			// 建立输出流，并写入数据
			OutputStream outputStream = httpConn.getOutputStream();
			outputStream.write(requestStringBytes);
			outputStream.close();
			// 获得响应状态
			int responseCode = httpConn.getResponseCode();
			if (HttpURLConnection.HTTP_OK != responseCode) {// 连接成功
				throw new IOException("HTTP Response code: " + responseCode);
			}
			// 获取返回数据字节数组
			arrayOfByte = StreamUtil.receiveData(httpConn.getInputStream());
			return arrayOfByte;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return arrayOfByte;
	}

	/**
	 * POST方式通过802.11B协议提交
	 * 
	 * @param postUrl
	 *            提交URL
	 * @param paramMap
	 *            参数Map集合
	 * @throws Exception
	 */
	private byte[] post_old(URI paramURI, Map<String, Object> paramMap)
			throws Exception {
		// 获取HttpHost对象
		HttpPost localHttpPost = new HttpPost(paramURI);
		// 添加参数信息
		List<NameValuePair> params = new ArrayList<NameValuePair>();
		Set<String> keys = paramMap.keySet();
		Object[] keyArray = keys.toArray();
		System.out.println(JSON.toJSONString(paramMap));
		for (int i = 0, len = keyArray.length; i < len; i++) {
			params.add(new BasicNameValuePair(String.valueOf(keyArray[i]),
					String.valueOf(paramMap.get(keyArray[i]))));
		}
		// FileEntity f = new ;
		UrlEncodedFormEntity postParamEntity = new UrlEncodedFormEntity(params,
				HTTP.UTF_8);
		// 设置内容类型
		postParamEntity.setContentType("application/x-www-form-urlencoded");
		localHttpPost.setEntity(postParamEntity);
		// 获取response对象
		HttpResponse localHttpResponse = this._client.execute(localHttpPost);
		// 获取状态值
		StatusLine localStatusLine = localHttpResponse.getStatusLine();
		if (localStatusLine.getStatusCode() != 200) {
			throw new IOException("HTTP Response code: "
					+ localStatusLine.getStatusCode() + " - "
					+ localStatusLine.getReasonPhrase());
		}
		// 获取返回数据字节数组
		byte[] arrayOfByte = StreamUtil.receiveData(localHttpResponse
				.getEntity().getContent());
		// 终止HTTP请求
		localHttpPost.abort();
		return arrayOfByte;
	}

	private byte[] post(String paramURI, Map<String, Object> paramMap) {
		byte[] arrayOfByte = null;
		try {
			// 建立连接
			URL url = new URL(paramURI);
			HttpURLConnection httpConn = (HttpURLConnection) url
					.openConnection();
			System.out.println("====" + paramURI);
			// //设置连接属性
			httpConn.setDoOutput(true);// 使用 URL 连接进行输出
			httpConn.setDoInput(true);// 使用 URL 连接进行输入
			httpConn.setUseCaches(false);// 忽略缓存
			httpConn.setRequestMethod("POST");// 设置URL请求方法
			String requestString = JSON.toJSONString(paramMap);
			System.out.println("====" + requestString);
			// 设置请求属性
			// 获得数据字节数据，请求数据流的编码，必须和下面服务器端处理请求流的编码一致
			byte[] requestStringBytes = requestString.getBytes(HTTP.UTF_8);
			httpConn.setRequestProperty("Content-length", ""
					+ requestStringBytes.length);
			httpConn.setRequestProperty("Content-Type",
					"application/octet-stream");
			httpConn.setRequestProperty("Connection", "Keep-Alive");// 维持长连接
			httpConn.setRequestProperty("Charset", "UTF-8");

			// 建立输出流，并写入数据
			OutputStream outputStream = httpConn.getOutputStream();
			outputStream.write(requestStringBytes);
			outputStream.close();
			// 获得响应状态
			int responseCode = httpConn.getResponseCode();
			if (HttpURLConnection.HTTP_OK != responseCode) {// 连接成功
				throw new IOException("HTTP Response code: " + responseCode);
			}
			// 获取返回数据字节数组
			arrayOfByte = StreamUtil.receiveData(httpConn.getInputStream());
			return arrayOfByte;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return arrayOfByte;
	}

	/**
	 * 根据URL获取主机名
	 * 
	 * @param postUrl
	 * @return
	 */
	private String getHostByUrl(String postUrl) {
		int i = postUrl.indexOf(":");
		String str = "";
		if (i < 0) {
			str = null;
		}
		int j = postUrl.indexOf(":", i + 1);
		if (j >= 0) {
			str = postUrl.substring(0, j);
			return str;
		}
		int k = postUrl.indexOf("/", i + 3);
		if (k >= 0) {
			str = postUrl.substring(0, k);
			return str;
		}
		return str;
	}

	/**
	 * 根据URL获取端口
	 * 
	 * @param postURL
	 * @return
	 */
	private String getPortByUrl(String postURL) {
		int i = postURL.indexOf(":");
		String str;
		if (i < 0) {
			str = "80";
		}
		int j = postURL.indexOf(":", i + 1);
		if (j < 0) {
			str = "80";
			return str;
		}
		int k = postURL.indexOf("/", j + 1);
		if (k < 0) {
			str = postURL.substring(j + 1);
			return str;
		}
		str = postURL.substring(j + 1, k);
		return str;
	}

	/**
	 * 参数拼接
	 * 
	 * @param paramMap
	 *            参数集合
	 * @return
	 * @throws Exception
	 */
	public String parametersToString(Map<String, Object> paramMap)
			throws Exception {
		Set<String> keys = paramMap.keySet();
		Object[] keyArray = keys.toArray();
		StringBuffer paramSB = new StringBuffer();
		String s = "";
		for (int i = 0, len = keyArray.length; i < len; i++) {
			paramSB.append(keyArray[i] + "=");
			// 参数进行URL编码
			paramSB.append(String.valueOf(paramMap.get(keyArray[i])));
			// if (i != len - 1) {
			// paramSB.append("&");
			// }
			paramSB.append("&");
		}
		s = paramSB.toString();
		System.out.println("==========" + s);
		return s;
	}
}